﻿using CameraWin;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Security.AccessControl;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ABELGX
{
    public class Car
    {
        public bool Run { get; set; } = true;
        #region 命令
        public CmdHeart CmdHeart { get;}
        public CmdWater CmdWater { get;}
        public CmdPTZ CmdPTZ { get;}
        public CmdCommon CmdCommon { get;}
        public CmdParam CmdParam { get; }
        public CmdArm CmdArm { get;}
        List<CarCmd> Cmds { get; }
        #endregion
        #region 反馈
        public InfoMotor InfoMotor { get; }
        public InfoDriver InfoDriver { get; }
        public InfoBattery InfoBattery { get;}
        public InfoCommon InfoCommon {  get;}
        public InfoAir InfoAir { get; }
        public InfoSensor InfoSensor {  get; }
        public InfoWarning InfoWarning { get; }
        public InfoArm InfoArm { get; }
        List<CarInfo> Infos { get; }
        #endregion
        public List<ICamera> Cameras { get; }
        public DateTime ControlTime { get; set; } = DateTime.Now;
        public Car(Parameter parameter)
        {
            var cmdSet = parameter.Cmds;
            CmdHeart = new CmdHeart(cmdSet.Find(x => x.Func == CarCmd.CMD_HEART), 6);
            CmdHeart.Cmd[4] = (byte)parameter.Car.ID;
            CmdHeart.Cmd[5] = (byte)(parameter.Car.ID >> 8);
            CmdHeart.Cmd[6] = (byte)parameter.Car.Version;
            CmdHeart.Cmd[7] = (byte)(parameter.Car.Version >> 8);


            CmdWater = new CmdWater(cmdSet.Find(x => x.Func == CarCmd.CMD_WATER), 9);
            CmdPTZ = new CmdPTZ(cmdSet.Find(x => x.Func == CarCmd.CMD_PTZ), 9);
            CmdCommon = new CmdCommon(cmdSet.Find(x => x.Func == CarCmd.CMD_COMMON), 10);
            CmdParam = new CmdParam(cmdSet.Find(x => x.Func == CarCmd.CMD_PARAM), 13);
            CmdParam.UserSet = Config.UserSet;
            CmdArm = new CmdArm(cmdSet.Find(x => x.Func == CarCmd.CMD_ARM), 23);

            Cmds = new List<CarCmd>
            {
                CmdWater,
                CmdPTZ,
                CmdCommon,
                CmdParam,
                CmdArm,
            };


            InfoMotor = new InfoMotor(CarInfo.INFO_MOTOR);
            InfoDriver = new InfoDriver(parameter.Car.DriverCount, CarInfo.INFO_DRIVER_STATUS, CarInfo.INFO_DRIVER_DATA);
            InfoBattery = new InfoBattery(parameter.Battery, CarInfo.INFO_BATTERY, CarInfo.INFO_BATTERY_VOLTAGE, CarInfo.INFO_BATTERY_TEMPERATURE);
            InfoCommon = new InfoCommon(parameter.Customize,CarInfo.INFO_COMMON);
            InfoAir = new InfoAir(parameter.AirSensors, CarInfo.INFO_AIR_DATA, CarInfo.INFO_AIR_STATUS);
            InfoSensor = new InfoSensor(parameter.GeneralSensors, CarInfo.INFO_SENSOR_DATA,CarInfo.INFO_SENSOR_STATUS);
            InfoWarning = new InfoWarning(CarInfo.INFO_WARNING);
            InfoArm = new InfoArm(CarInfo.INFO_ARM);
            Infos = new List<CarInfo>
            {
                InfoMotor,
                InfoDriver,
                InfoBattery,
                InfoCommon,
                InfoAir,
                InfoSensor,
                InfoWarning,
                InfoArm
            };

            Cameras = new List<ICamera>();
            foreach(var cam in parameter.Cameras)
            {
                Cameras.Add(new Camera(Cameras.Count,cam));
            }
            Cameras[0].Main = true;
        }
        public void InitInfo()
        {
            foreach(var info in Infos)
            {
                info.InitData();
            }
        }
        public void Sync()
        {

        }
        public byte[] GetCmd()
        {
            if(CmdHeart.CanSend)
            {
                CmdHeart.SendTime = DateTime.Now;
                return CmdHeart.GetCmd();
            }
            if(CmdHeart.Lock && CmdCommon.Control == ControlType.SBUS)
            {
                return null;
            }
            var cmd = Cmds.Find(x=>x.CanSend);
            if (cmd == null)
            {
                return null;
            }
            cmd.SendTime = DateTime.Now;
            return cmd.GetCmd();
        }

        public void ProcessData(byte[] data, int start)
        {
            var infos = Infos.FindAll(x => x.Funcs.Exists(y => y == data[start]));
            foreach(var info in infos)
            {
                info.ProcessData(data, start);
            }
        }
    }
}
